<!--
 * @Descripttion: 坝前水位
 * @version: 
 * @Author: xcb
 * @Date: 2021-03-16 09:48:46
 * @LastEditors: gzy 810461372@qq.com
 * @LastEditTime: 2023-09-22 14:54:51
-->
<template>
  <el-row style="height: 100%">
    <el-col :span="18">
      <div id="schemePresetEcharts" style="width: 100%; height: 100%"></div>
    </el-col>
    <el-col :span="6" style="height: 100%">
      <el-button
        style="width: 100%; margin-bottom: 10px"
        type="primary"
        :disabled="
          !planDataMsgForm.verifyUser ||
          planDataMsgForm.predictDay === 0 ||
          planDataMsgForm.selectReservoir != '三峡库区'
        "
        @click="predictiveCalculation"
      >
        预测水位计算
      </el-button>

      <el-table
        size="small"
        style="width: 100%"
        max-height="320px"
        :data="tableData"
        border
        stripe
        :row-key="(row) => row.tm"
        @cell-dblclick="cellDblclick"
        @cell-mouse-leave="cellMouseLeave"
      >
        <el-table-column label="时间" prop="tm"> </el-table-column>
        <el-table-column label="出库流量(m³/s)" prop="otq">
          <template #default="scope">
            <div>
              <el-input
                v-if="editableData[scope.row.tm]"
                v-model="editableData[scope.row.tm].otq"
                size="small"
              />
              <template v-else>
                {{ scope.row.otq }}
              </template>
            </div>
          </template>
        </el-table-column>
      </el-table>
    </el-col>
  </el-row>
</template>

<script lang="ts">
import { cloneDeep } from "lodash-es";
import {
  ref,
  defineComponent,
  inject,
  reactive,
  watch,
  toRefs,
  onMounted,
} from "vue";
import * as echarts from "echarts";
import moment, { Moment } from "moment";

import { getWaterLevelList } from "@/request/api";

export default defineComponent({
  name: "schemePreset",
  props: {
    // 树状图数据
    treeData: {
      type: Object,
      default: () => {},
    },
  },
  setup: (props) => {
    const state = reactive({
      tableData: [],
      editableData: {},
    });

    // 坝前水位数据
    let schemePresetData: any = inject("schemePresetData");

    // 方案参数信息
    const planDataMsgForm: any = inject("planDataMsgForm");

    watch(
      () => schemePresetData,
      (value: any, prevCount) => {
        if (Object.keys(value).length != 0) {
          echartsInit(value);
        }
      },
      { deep: true }
    );

    onMounted(() => {
      setTimeout(() => {
        echartsInit(schemePresetData);
      }, 100);
    });

    /**
     * @description: 图表生成
     * @param {*} Data 图表数据
     * @return {*}
     */
    function echartsInit(chartData) {
      const elem = document.getElementById("schemePresetEcharts");

      elem.removeAttribute("_echarts_instance_");

      const myChart = echarts.init(elem);

      myChart.clear();

      let option = {
        title: {
          text: "坝前水位",
          left: "center",
        },
        tooltip: {
          trigger: "axis",
        },
        grid: {
          left: 60,
          right: 50,
          bottom: 70,
        },
        legend: {
          data: [
            "水位",
            "入库流量",
            "出库流量",
            "长江委: 水位",
            "长江委: 入库流量",
            "长江委: 出库流量",
          ],
          x: "center",
          top: "6%",
          type: "scroll",
          width: "80%",
          selected: {
            水位: true,
            入库流量: true,
            出库流量: true,
            "长江委: 水位": true,
            "长江委: 入库流量": true,
          },
        },
        dataZoom: [
          {
            show: true,
            realtime: true,
            start: 0,
            end: 100,
            xAxisIndex: [0],
          },
        ],
        xAxis: {
          type: "time",
          splitLine: { show: true },
          axisTick: {
            show: true,
            inside: true,
          },
          axisLabel: {
            formatter: (value) => {
              return moment(value).format("YYYY-MM-DD HH");
            },
          },
        },
        yAxis: [
          {
            name: "水位(m)",
            type: "value",
            splitLine: { show: true },
            scale: true,
            axisLine: {
              show: true,
            },
            axisTick: {
              show: true,
              inside: true,
            },
            min: (value) => {
              return Math.round(value.min * 0.99);
            },
            max: (value) => {
              return Math.round(value.max * 1.01);
            },
          },
          {
            id: "y1",
            name: "流量(m³/s)",
            type: "value",
            splitLine: { show: false },
            scale: true,
            axisLine: {
              show: true,
            },
            axisTick: {
              show: true,
              inside: true,
            },
            min: (value) => {
              return Math.round(value.min * 0.99);
            },
            max: (value) => {
              return Math.round(value.max * 1.01);
            },
          },
        ],
        series: [
          {
            name: "水位",
            data: chartData.list
              .map((item) => [
                moment(item.tm).format("YYYY-MM-DD HH:mm:ss"),
                item.rz,
              ])
              .filter((item) => item[1]),
            type: "line",
            symbol: "none",
            itemStyle: {
              color: "#ff00ff",
            },
          },
          {
            name: "入库流量",
            data: chartData.list
              .map((item) => [
                moment(item.tm).format("YYYY-MM-DD HH:mm:ss"),
                item.inq,
              ])
              .filter((item) => item[1]),
            yAxisIndex: 1,
            type: "line",
            symbol: "none",
            connectNulls: true,
            itemStyle: {
              color: "#ff7f50",
            },
          },
          {
            name: "出库流量",
            data: chartData.list
              .map((item) => [
                moment(item.tm).format("YYYY-MM-DD HH:mm:ss"),
                item.otq,
              ])
              .filter((item) => item[1]),
            yAxisIndex: 1,
            type: "line",
            symbol: "none",
            itemStyle: {
              color: "#1a77bb",
            },
          },
          {
            name: "长江委: 水位",
            data:
              planDataMsgForm.predictDay != 0
                ? chartData.swjList.map((item) => [
                    moment(item.ymdh).format("YYYY-MM-DD HH:mm:ss"),
                    item.z,
                  ])
                : [],
            type: "line",
            symbol: "none",
            lineStyle: {
              type: "dashed",
            },
            itemStyle: {
              color: "#ff00ff",
            },
            animation: false,
          },
          {
            name: "长江委: 入库流量",
            data:
              planDataMsgForm.predictDay != 0
                ? chartData.swjList.map((item) => [
                    moment(item.ymdh).format("YYYY-MM-DD HH:mm:ss"),
                    item.q,
                  ])
                : [],
            yAxisIndex: 1,
            type: "line",
            symbol: "none",
            lineStyle: {
              type: "dashed",
            },
            itemStyle: {
              color: "#ff7f50",
            },
            animation: false,
          },
          {
            name: "长江委: 出库流量",
            data:
              planDataMsgForm.predictDay != 0
                ? chartData.otqList.map((item) => [
                    moment(item.tm).format("YYYY-MM-DD HH:mm:ss"),
                    item.otq,
                  ])
                : [],
            yAxisIndex: 1,
            type: "line",
            itemStyle: {
              color: "#1a77bb",
            },
            animation: false,
          },
        ],
      };

      myChart.setOption(option);

      setTimeout(() => {
        myChart.resize();
      }, 0);

      if (planDataMsgForm.predictDay != 0) {
        // 生成右侧表格数据
        state.tableData = chartData.otqList.map((item) => {
          return {
            tm: moment(item.tm).format("YYYY-MM-DD HH:mm:ss"),
            otq: item.otq,
          };
        });

        // 出库流量拖拽注册
        pointDrag(
          myChart,
          "长江委: 出库流量",
          chartData.otqList.map((item) => [item.tm, item.otq])
        );
      } else {
        state.tableData = [];
      }
    }

    /**
     * @description: 拖拽事件注册
     * @param {*} myChart 图表实例
     * @param {*} name 需要更新的series数据name
     * @param {*} data 需要拖拽的数据
     * @return {*}
     */
    function pointDrag(myChart, name, data) {
      myChart.setOption({
        graphic: data.map(function (item, dataIndex) {
          return {
            type: "circle",
            position: myChart.convertToPixel(
              { xAxisIndex: 0, yAxisId: "y1" },
              item
            ),
            z: 100,
            shape: {
              x: 0,
              y: 0,
              r: 10,
            },
            invisible: true,
            draggable: true,
            ondrag: echarts.util.curry(function (dataIndex) {
              // 此处必须用匿名函数，不能用箭头函数，否则拿不到拖动的坐标
              let origin = myChart.convertToPixel(
                { xAxisIndex: 0, yAxisId: "y1" },
                data[dataIndex]
              ); // 得到每个圆点原始位置
              this.position[0] = origin[0]; // 控制每个点位只能在y轴方向移动

              // 实时获取拖动的点位信息并根据此信息重新画图
              data[dataIndex] = myChart.convertFromPixel(
                { xAxisIndex: 0, yAxisId: "y1" },
                this.position
              );

              // 拖拽值改为1000
              data[dataIndex][1] += data[dataIndex][1] % 1000 > 500 ? 1000 : 0;

              data[dataIndex][1] =
                data[dataIndex][1] - (data[dataIndex][1] % 1000);

              // 时间拖拽后会有小数点 将小数点向上取整
              data[dataIndex][0] = Number(data[dataIndex][0].toFixed(0));
              // 修改右侧表格内数据
              state.tableData.find(
                (item) =>
                  moment(item.tm).format("YYYY-MM-DD HH:mm:ss") ==
                  moment(data[dataIndex][0]).format("YYYY-MM-DD HH:mm:ss")
              ).otq = data[dataIndex][1];

              // 更新图表
              myChart.setOption({
                series: [
                  {
                    name: name,
                    data: data,
                    yAxisIndex: 1,
                    type: "line",
                  },
                ],
              });
            }, dataIndex),

            onmouseup: () => {
              updatePosition(myChart, data);
            },
          };
        }),
      });

      window.addEventListener("resize", () => {
        updatePosition(myChart, data);
        myChart.resize();
      });

      myChart.on("dataZoom", () => {
        updatePosition(myChart, data);
      });
    }

    /**
     * @description: 更新图表中点位置
     * @param {*} myChart 图表实例
     * @param {*} data 需要更新的位置
     * @return {*}
     */
    function updatePosition(myChart, data) {
      myChart.setOption({
        graphic: data.map(function (item, dataIndex) {
          return {
            position: myChart.convertToPixel(
              { xAxisIndex: 0, yAxisId: "y1" },
              item
            ),
          };
        }),
      });
    }

    /**
     * @description: 右侧表格鼠标双击事件
     * @param {*} tm 当前行时间（用作行唯一key判断）
     * @return {*}
     */
    function cellDblclick({ tm }) {
      // 将当前数据深拷贝一份用于修改
      state.editableData[tm] = cloneDeep(
        state.tableData.find((item) => item.tm == tm)
      );
    }

    /**
     * @description: 右侧表格鼠标移开事件
     * @param {*} tm 当前行时间（用作行唯一key判断）
     * @return {*}
     */
    function cellMouseLeave({ tm }) {
      // 将修改后的数据重新赋值回右侧表格
      Object.assign(
        state.tableData.filter((item) => item.tm == tm)[0],
        state.editableData[tm]
      );

      // 删除掉编辑所用到的数据
      delete state.editableData[tm];

      // 将表格数据转成图表数据
      const otqData = state.tableData.map((item) => {
        return [
          moment(item.tm).format("YYYY-MM-DD HH:mm:ss"),
          Number(item.otq),
        ];
      });

      // 更新图表数据
      let myChart = echarts.init(
        document.getElementById("schemePresetEcharts")
      );

      myChart.setOption({
        series: [
          {
            name: "长江委: 出库流量",
            data: otqData,
            yAxisIndex: 1,
            type: "line",
          },
        ],
      });

      // 根据修改后的新数据重新注册拖拽事件
      pointDrag(myChart, "长江委: 出库流量", otqData);
      // 更新图表内的拖拽点位
      updatePosition(myChart, otqData);
    }

    /**
     * @description: 预测水位计算
     * @return {*}
     */
    function predictiveCalculation() {
      getWaterLevelList({
        otqList: schemePresetData.otqList.map((item, i) => {
          item.otq = Number(state.tableData[i].otq);
          return item;
        }),
        swjList: schemePresetData.swjList,
      }).then((res: any) => {
        // 根据现在图表数据循环 将返回值中的数据插入
        schemePresetData.swjList.forEach((item) => {
          item.z = res.find(
            (ele) =>
              moment(ele.time).format("YYYY-MM-DD HH:mm:ss") ===
              moment(item.ymdh).format("YYYY-MM-DD HH:mm:ss")
          ).elv;
        });

        // 根据新图表数据重新生成图表
        echartsInit(schemePresetData);
      });
    }

    return {
      ...toRefs(state),

      cellDblclick,
      cellMouseLeave,

      predictiveCalculation,
      planDataMsgForm,
    };
  },
});
</script>

<style scoped lang="less"></style>
